BOOTSEG = 0x1000
.globl begtext, begdata, begbss                      ! needed by linker

! IMPORTS and EXPORTS
.globl _main,_prints,_running,_scheduler			 !imports
.globl _processSize,_syscallHandler					 !imports
.globl _getc,_putc,_diskr,_setes,_inces,_tswitch	 !exports
.globl _int80h,_goUmode,_get_byte,_put_byte,_getcs	 !exports

.text                                                ! these tell as:	
begtext:                                             ! text,data,bss segments
.data                                                ! are all the same.
begdata:
.bss
begbss:
.text           

start:
        mov     ax,cs                   ! establish segments 
        mov     ds,ax                   ! we know ES,CS=0x1000. Let DS=CS  
        mov     ss,ax                   ! SS = CS ===> all point to 0x1000
        mov     es,ax
        mov     sp,#0                   ! SP = 64KB

        call _main                      ! call main[] in C

! if ever return, just hang
		mov		ax,#msg
		push	ax
		call	_prints
dead:	jmp dead
msg:	.asciz "BACK TO ASSEMBLY AND HANG\r\n"

!*************************************************************
!     KCW  added functions for MT system
!************************************************************
_getcs:
        mov   ax, cs
        ret

_tswitch:
		push	ax
        push	bx
        push	cx
        push	dx
        push	bp
        push	si
        push	di
        pushf
        mov		bx, _running
        mov		2[bx], sp

		find:
		call	_scheduler

		resume:
		mov		bx, _running
        mov		sp, 2[bx]
        popf
        pop		di
        pop		si
        pop		bp
        pop		dx
        pop		cx
        pop		bx
        pop		ax
        ret

_int80h:
		push	ax
		push	bx
		push	cx
		push	dx
		push	bp
		push	si
		push	di
		push	es
		push	ds
		
		! ustack contains: flag,uCS,uPC,ax,bx,cx,dx,bp,si,di,uES,uDS
		push	cs
		pop		ds
		
		mov 	si,_running
		mov		4[si],ss
		mov		6[si],sp
		
		! change ES,SS to kernel segment
		mov		di,ds
		mov		es,di
		mov		ss,di
		
		! set sp to HI end of running kstack
		mov		sp,_running
		add		sp,_processSize
		
		call	_syscallHandler
		jmp		_goUmode
		
_goUmode:
		cli
		mov		bx,_running
		mov		cx,4[bx]
		mov		ss,cx
		mov		sp,6[bx]
		
		pop		ds
		pop		es
		pop		di
		pop		si
		pop		bp
		pop		dx
		pop		cx
		pop		bx
		pop		ax
		
		iret
		
       !---------------------------------------
       ! int diskr[cyl, head, sector, buf] 
       !            4     6     8     10
       !---------------------------------------
_diskr:
		push	bp
		mov		bp,sp
		
		movb	dl,#0x00
		movb	dh,6[bp]
		movb	cl,8[bp]
		incb	cl
		movb	ch,4[bp]
		mov		ax,#0x0202
		mov		bx,10[bp]
		int		0x13
		jb		error
		
		mov		sp,bp
		pop		bp
		ret

		!---------------------------------------------
        !  char getc[]   function: returns a char
        !---------------------------------------------
_getc:
        xorb   ah,ah 
        int    0x16  
        ret 

		!----------------------------------------------
        ! void putc[char c]  function: print a char
        !----------------------------------------------
_putc:           
        push	bp
        mov		bp,sp
        
        movb	al,4[bp]
        movb	ah,#14
        
        mov		bx,#0x000B 
        int		0x10
        
        mov		sp,bp
        pop		bp
        ret

_setes:
		push	bp
		mov		bp,sp
		
		mov		ax,4[bp]
		mov		es,ax
		
		mov		sp,bp
		pop		bp
		ret
		
_inces:
		mov		ax,es
		add		ax,#0x40
		mov		es,ax
		ret
		
		!------------------------------
        !       error & reboot
        !------------------------------
error:
		mov		bx,#bad
		push	bx
		call	_prints
		int		0x19

bad:	.asciz	"Error!\r\n"

!*===========================================================================*
!*								 get_byte								     *
!*===========================================================================*
! This routine is used to fetch a byte from anywhere in memory.
! The call is:
!     c = get_byte[segment, offset]
! where
!     'segment' is the value to put in es
!     'offset'  is the offset from the es value
_get_byte:
		push	bp
		mov		bp,sp
		
		push	es
		push	bx
		
		mov		es,4[bp]
		mov		bx,6[bp]
		seg		es
		movb	al,[bx]
		xorb	ah,ah
		
		pop		bx
		pop		es
		
		mov		bp,sp
		pop		bp
		ret
		
!*===========================================================================*
!*								 put_byte									 *
!*===========================================================================*
! This routine is used to put a word to anywhere in memory.
! The call is:
!           put_byte[char,segment,offset]
! where
!     char is a byte
!     'segment' is a segment
!     'offset'  is the offset from the segment
_put_byte:
		push	bp
		mov		bp,sp
		
		push	es
		push	bx
		
		mov		es,6[bp]
		mov		bx,8[bp]
		mov		al,4[bp]
		seg		es
		movb	[bx],al
		
		pop		bx
		pop		es
		
		mov		bp,sp
		pop		bp
		ret
